home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / Simple Help / SimpleHelp.c < prev    next >
Text File  |  1994-09-15  |  18KB  |  741 lines

  1. /****************************************************************************************
  2. *
  3. *
  4. *        SimpleHelp.c        -implementation of simplehelp system
  5. *
  6. *        ©1994, Graham Cox. All Rights Reserved.
  7. *
  8. *        9/2/94
  9. *        28/6/94        First List Item now Hilited on startup of help
  10. *                    Hypertext links now track mouse like buttons
  11. *                    Links flash on mouse up like menus
  12. *                    SetHyperlinkMatchStyle now correctly sets up data internally
  13. *                    Buttons now correctly hilited at startup of help
  14. *                    Now handles up and down arrow keys to select topics
  15. *        29/6/94        Manages resource file correctly for when help is a seperate file
  16. *        14/7/94        Reworked to compile under CodeWarrior for the PowerPC
  17. *
  18. ****************************************************************************************/
  19.  
  20. #include    "SimpleHelpTypes.h"
  21. #include    "ColourPopUp.h"
  22. #include    <Errors.h>
  23.  
  24. #define SetHiliteMode()        LMSetHiliteMode(LMGetHiliteMode() &! hiliteBit)
  25.  
  26. Handle    GetUniversalFunctionHandle(ProcPtr functionAddress,ProcInfoType pInfo);
  27.  
  28.                             
  29. ListHandle    gTopicList = NIL;
  30.  
  31. void    DrawHelpTopicCell(Cell tCell,short dataLen,ListHandle theList,Rect *dCell);
  32.  
  33. #define        helpTopicTitle    7
  34.  
  35. OSErr        BuildTopicList(SimHelpHdl sHelp,Rect *listBox)
  36. {
  37.     /* this function builds the topic list. It first creates the list manager record and
  38.         installs the custom draw proc. It then opens the resource which defines the topic
  39.         list, and reads in each entry, storing it in the list. The sHelp record (which
  40.         must already have been created and otherwise initialised) has the list handle
  41.         stored into it. */
  42.         
  43.     ListHandle        theList;
  44.     topicListHdl    topicList;
  45.     topicRecPtr        topicEntry;
  46.     Rect            dataBounds;
  47.     Point            cSize;
  48.     short            index;
  49.     Cell            curCell;
  50.     short            recSize;
  51.     OSErr            btErr = memFullErr;
  52.     Handle            funcLDEF;
  53.     
  54.     if (sHelp != NIL)
  55.     {
  56.         topicList = (topicListHdl) GetResource(topicListResType,(*sHelp)->topicID);
  57.         
  58.         btErr = ResError();
  59.         
  60.         if (topicList != NIL)
  61.         {
  62.             HNoPurge((Handle) topicList);
  63.             
  64.             SetRect(&dataBounds,0,0,1,(*topicList)->nTopics + 1);
  65.             SetPt(&cSize,0,0);
  66.             listBox->right -= 15;        // allow for scrollbar
  67.             InsetRect(listBox,1,1);        // and frame
  68.             
  69.             theList = LNew(listBox,&dataBounds,cSize,0,(*sHelp)->ownerWindow,
  70.                             FALSE,FALSE,FALSE,TRUE);
  71.             
  72.             InsetRect(listBox,-1,-1);
  73.             listBox->right += 15;
  74.  
  75.             if (theList != NIL)
  76.             {
  77.                 MoveHHi((Handle) topicList);
  78.                 HLock((Handle) topicList);
  79.                 topicEntry = &(*topicList)->theTopic;
  80.                 curCell.v = 0;
  81.                 curCell.h = 0;
  82.                 
  83.                 for(index = 0;index <= (*topicList)->nTopics;index++)
  84.                 {
  85.                     recSize = sizeof(topicRec) + topicEntry->topicString - 1;
  86.                     
  87.                     LSetCell((Ptr) topicEntry,recSize,curCell,theList);
  88.                     
  89.                     topicEntry = (topicRecPtr)((long)topicEntry + recSize);
  90.                                                 // point at next record (variable size)
  91.                     curCell.v++;
  92.                 }
  93.                 HUnlock((Handle) topicList);
  94.                 
  95.                 (*sHelp)->topicList = theList;    // set record field
  96.                 
  97.                 funcLDEF = GetUniversalFunctionHandle((ProcPtr)TopicListDef,uppListDefProcInfo);
  98.                 (*theList)->listDefProc = funcLDEF;
  99.                 (*theList)->userHandle = (Handle) sHelp;
  100.             }    
  101.             HPurge((Handle) topicList);
  102.             ReleaseResource((Handle) topicList);
  103.         }
  104.     }
  105.     return(btErr);
  106. }
  107.  
  108.  
  109. SimHelpHdl    GetNewHelpDialog(short DialogID,short listItem,short textItem,short topicID)
  110. {
  111.     /* highish level call to get the dialog and build its internal data structures. These
  112.         include the scrolling text panel and the topic list */
  113.         
  114.     SimHelpHdl    sHelp = NIL;
  115.     DialogPtr    helpDialog;
  116.     OSErr        btErr;
  117.     Rect        rViewRect;
  118.     short        itemType;
  119.     Handle        itemHand;
  120.     GrafPtr        savePort;
  121.     Cell        firstCell = {0,0};
  122.     static UserItemUPP    gMyUserItemUPP;
  123.     
  124.     helpDialog = GetTextDialog(DialogID,textItem,defaultTextResID,FALSE);
  125.     
  126.     if (helpDialog != NIL)
  127.     {
  128.         sHelp = (SimHelpHdl) NewHandleClear(sizeof(SimHelpRecord));
  129.     
  130.         if (sHelp != NIL)
  131.         {
  132.             (*sHelp)->ownerWindow = helpDialog;
  133.             (*sHelp)->topicID = topicID;
  134.             (*sHelp)->indentPixels = defaultIndent;
  135.             (*sHelp)->listItemID = listItem;
  136.             (*sHelp)->textItemID = textItem;
  137.             (*sHelp)->helpResFileRef = -1;
  138.             (*sHelp)->swapResFileRef = -1;
  139.             
  140.             GetPort(&savePort);
  141.             SetPort(helpDialog);
  142.             TextFont(defaultFont);
  143.             TextSize(defaultFontSize);
  144.             
  145.             (*sHelp)->missingPageID = pageMissingStrID;
  146.             (*sHelp)->fontID = defaultFont;
  147.             (*sHelp)->fontSize = defaultFontSize;
  148.             
  149.             (*sHelp)->hyperTextStyle = bold;    // default style for hypertext
  150.             (*sHelp)->hyperTextIndex = -1;        // index not initialised
  151.             
  152.             GetDItem(helpDialog,listItem,&itemType,&itemHand,&rViewRect);
  153.             if ((itemType & 0x7F) == userItem)
  154.             {
  155.                 btErr = BuildTopicList(sHelp,&rViewRect);
  156.                 
  157.                 gTopicList = (*sHelp)->topicList;        // annoyingly necessary...
  158.             
  159.                 gMyUserItemUPP = NewUserItemProc((ProcPtr) ListDrawProc);
  160.                 itemHand = (Handle) gMyUserItemUPP;
  161.                 SetDItem(helpDialog,listItem,itemType,itemHand,&rViewRect);
  162.             }
  163.             LDoDraw(TRUE,gTopicList);
  164.             LActivate(TRUE,gTopicList);
  165.             LSetSelect(TRUE,firstCell,(*sHelp)->topicList);
  166.  
  167.             TextFont(0);
  168.             TextSize(12);
  169.             
  170.             SwitchPage(sHelp,(*sHelp)->lastSelection);
  171.             itemType = helpPrevButton;
  172.             HandleHelpItems(sHelp,&itemType);
  173.  
  174.             SetPort(savePort);
  175.         }
  176.     }
  177.     
  178.     return(sHelp);
  179. }
  180.  
  181.  
  182. void    DisposeHelpDialog(SimHelpHdl sHelp)
  183. {
  184.     /* disposes of everything, including dialog box itself */
  185.     
  186.     Handle        defProc;
  187.     
  188.     if (sHelp != NIL)
  189.     {
  190.         defProc = (*(*sHelp)->topicList)->listDefProc;
  191.         LDispose((*sHelp)->topicList);
  192.         gTopicList = NIL;
  193.         DisposHandle(defProc);
  194.         DisposeTDDialog((*sHelp)->ownerWindow);
  195.         DisposHandle((Handle) sHelp);
  196.     }
  197. }
  198.  
  199.  
  200. void    SetHyperlinkMatchStyle(SimHelpHdl sHelp,short theStyle)
  201. {
  202.     short        hypIndex;
  203.     TEHandle    teRec;
  204.     
  205.     if (sHelp != NIL)
  206.     {
  207.         (*sHelp)->hyperTextStyle = theStyle;
  208.         teRec = GetTDTextHdl((*sHelp)->ownerWindow);
  209.         hypIndex = GetHypertextStyleRef(teRec,theStyle);
  210.         (*sHelp)->hyperTextIndex = hypIndex;
  211.     }
  212. }
  213.  
  214.  
  215. DialogPtr    GetHelpDialogHdl(SimHelpHdl sHelp)
  216. {
  217.     /* returns the dialog field */
  218.     
  219.     if (sHelp != NIL)
  220.         return((*sHelp)->ownerWindow);
  221.     else
  222.         return(NIL);
  223. }
  224.  
  225.  
  226. void    ModalHelpDialog(SimHelpHdl sHelp,short *theItem)
  227. {
  228.     /* call replacement for ModalDialog. Handles list and text clicks, etc */
  229.     
  230.     while (*theItem == 0)
  231.     {
  232.         ModalTDDialog((short*)theItem);
  233.         HandleHelpItems(sHelp,theItem);
  234.     }
  235. }
  236.  
  237.  
  238. Boolean        HandleHelpItems(SimHelpHdl sHelp,short *theItem)
  239. {
  240.     Point    mClick;
  241.     GrafPtr    savePort;
  242.     Cell    lastOne,thisOne;
  243.     short    itemType;
  244.     Handle    itemHand;
  245.     Rect    itemBox;
  246.     Boolean    retCode = FALSE;
  247.  
  248.     thisOne = lastOne = (*sHelp)->lastSelection;
  249.  
  250.     if (*theItem == (*sHelp)->listItemID)
  251.     {
  252.         *theItem = 0;
  253.         
  254.         /* handle list clicks */
  255.         GetPort(&savePort);
  256.         SetPort((*sHelp)->ownerWindow);
  257.         GetMouse(&mClick);
  258.         
  259.         LClick(mClick,0,(*sHelp)->topicList);
  260.         SetPt(&thisOne,0,0);
  261.         if (LGetSelect(TRUE,&thisOne,(*sHelp)->topicList))
  262.         {
  263.             if (!EqualPt(thisOne,lastOne))
  264.             {
  265.                 SwitchPage(sHelp,thisOne);
  266.                 (*sHelp)->lastSelection = thisOne;
  267.             }
  268.         }
  269.         SetPort(savePort);
  270.         retCode = TRUE;
  271.     }
  272.     else
  273.     {
  274.         switch (*theItem)
  275.         {
  276.             case helpNextButton:
  277.                 thisOne.v++;
  278.                 if (thisOne.v >= (*(*sHelp)->topicList)->dataBounds.bottom)
  279.                     thisOne.v = (*(*sHelp)->topicList)->dataBounds.bottom -1;
  280.                 else
  281.                 {
  282.                     LSetSelect(FALSE,lastOne,(*sHelp)->topicList);
  283.                     LSetSelect(TRUE,thisOne,(*sHelp)->topicList);
  284.                     LAutoScroll((*sHelp)->topicList);
  285.                     (*sHelp)->lastSelection = thisOne;
  286.                     SwitchPage(sHelp,thisOne);
  287.                 }
  288.                 *theItem = 0;
  289.                 retCode = TRUE;
  290.                 break;
  291.             case helpPrevButton:
  292.                 thisOne.v--;
  293.                 if (thisOne.v < 0)
  294.                     thisOne.v = 0;
  295.                 else
  296.                 {
  297.                     LSetSelect(FALSE,lastOne,(*sHelp)->topicList);
  298.                     LSetSelect(TRUE,thisOne,(*sHelp)->topicList);
  299.                     LAutoScroll((*sHelp)->topicList);
  300.                     (*sHelp)->lastSelection = thisOne;
  301.                     SwitchPage(sHelp,thisOne);
  302.                 }
  303.                 *theItem = 0;
  304.                 retCode = TRUE;
  305.                 break;
  306.         }
  307.     }
  308.     if (thisOne.v == (*(*sHelp)->topicList)->dataBounds.bottom -1)
  309.     {
  310.         GetDItem((*sHelp)->ownerWindow,
  311.                 helpNextButton,&itemType,&itemHand,&itemBox);
  312.         HiliteControl((ControlHandle)itemHand,255);
  313.     }    
  314.     if (thisOne.v != 0)
  315.     {
  316.         GetDItem((*sHelp)->ownerWindow,
  317.                 helpPrevButton,&itemType,&itemHand,&itemBox);
  318.         HiliteControl((ControlHandle) itemHand,0);
  319.     }
  320.     if (thisOne.v == 0)
  321.     {
  322.         GetDItem((*sHelp)->ownerWindow,
  323.                 helpPrevButton,&itemType,&itemHand,&itemBox);
  324.         HiliteControl((ControlHandle)itemHand,255);
  325.     }    
  326.     if (thisOne.v != (*(*sHelp)->topicList)->dataBounds.bottom -1)
  327.     {
  328.         GetDItem((*sHelp)->ownerWindow,
  329.                 helpNextButton,&itemType,&itemHand,&itemBox);
  330.         HiliteControl((ControlHandle) itemHand,0);
  331.     }
  332.     return(retCode);
  333. }
  334.  
  335.  
  336.  
  337. pascal void    ListDrawProc(WindowPtr theWindow,short theItem)
  338. {
  339.     /* user item draw proc for the list. a TAD tricky because we haven't got the list
  340.         handle- the refcon field is already in use by the scroll panel... */
  341.         
  342.     short        itemType;
  343.     Handle        itemHand;
  344.     Rect        itemBox;
  345.     RGBColor    saveBack;
  346.     
  347.     GetDItem(theWindow,theItem,&itemType,&itemHand,&itemBox);
  348.     
  349.     if (gTopicList != NIL)
  350.         LUpdate(qd.thePort->visRgn,gTopicList);
  351.     
  352.     Frame3DRect(&itemBox,FALSE);    // Godrilla Mincefriend
  353.     FrameRect(&itemBox);
  354. }
  355.  
  356.  
  357. void    SwitchPage(SimHelpHdl sHelp,Cell clickCell)
  358. {
  359.     /* looks up the text page for the given cell and installs that page */
  360.     
  361.     ListHandle        theList;
  362.     short            dLen;
  363.     bigTopicRec        btRec;
  364.     
  365.     if (sHelp != NIL)
  366.     {
  367.         theList = (*sHelp)->topicList;
  368.         
  369.         dLen = sizeof(bigTopicRec);
  370.         LGetCell(&btRec,&dLen,clickCell,theList);
  371.         InstallPage(sHelp,btRec.pageID);
  372.         ParamText(btRec.topicString,NIL,NIL,NIL);
  373.     }
  374. }
  375.  
  376.  
  377. void    InstallPage(SimHelpHdl sHelp,short pageID)
  378. {
  379.     Handle            theText;
  380.     StringHandle    errStr;
  381.     TEHandle        teRec;
  382.     short            hypIndex;
  383.     
  384.     if (sHelp != NIL)
  385.     {
  386.         if (pageID != 0)
  387.         {
  388.             SwapHelpResFile(sHelp,kSwapHelpIn);
  389.             
  390.             theText = GetResource('TEXT',pageID);        // preflight check
  391.             if (theText == NIL)
  392.             {
  393.                 errStr = GetString((*sHelp)->missingPageID);
  394.                 TDSetText((*sHelp)->ownerWindow,((Ptr)*errStr) +1,*errStr[0],NIL);
  395.                 (*sHelp)->curPageResID = 0;
  396.             }
  397.             else
  398.             {
  399.                 TDSetResourceText((*sHelp)->ownerWindow,pageID);
  400.                 (*sHelp)->curPageResID = pageID;
  401.             }
  402.             
  403.             teRec = GetTDTextHdl((*sHelp)->ownerWindow);
  404.             hypIndex = GetHypertextStyleRef(teRec,(*sHelp)->hyperTextStyle);
  405.             (*sHelp)->hyperTextIndex = hypIndex;
  406.             
  407.             SwapHelpResFile(sHelp,kSwapHelpOut);
  408.         }
  409.         else
  410.         {
  411.             TDSetText((*sHelp)->ownerWindow,(Ptr)*errStr,0,NIL);
  412.             (*sHelp)->curPageResID = 0;
  413.         }
  414.     }
  415. }
  416.  
  417.  
  418. pascal Boolean    ModelessHelp(SimHelpHdl sHelp,short theItem,EventRecord *theEvent)
  419. {
  420.     /* handles a modeless help window. Call after DialogSelect if it returns TRUE. */
  421.     
  422.     Boolean        mtResult;
  423.     short        htLink;
  424.     char        keyHit;
  425.     
  426.     if (sHelp != NIL)
  427.     {
  428.         mtResult = ModelessText((*sHelp)->ownerWindow,theItem,theEvent);
  429.         
  430.         if (! mtResult)
  431.         {
  432.             switch(theEvent->what)
  433.             {
  434.                 case mouseDown:
  435.                     if (! HandleHelpItems(sHelp,&theItem))
  436.                     {
  437.                         htLink = ResolveHypertextLink(sHelp,theEvent->where);
  438.                         
  439.                         if (htLink != -1)
  440.                         {
  441.                             /* we clicked a hypertext link. Unhilite the pick list and switch to
  442.                                 the page resolved */
  443.                                 
  444.                             LSetSelect(FALSE,(*sHelp)->lastSelection,(*sHelp)->topicList);
  445.                             (*sHelp)->lastSelection.v = -1;
  446.                             InstallPage(sHelp,htLink);
  447.                         }
  448.                         return(FALSE);
  449.                     }
  450.                     else
  451.                         return(TRUE);
  452.                     break;
  453.                 case keyDown:
  454.                 case autoKey:
  455.                     keyHit = theEvent->message & charCodeMask;
  456.                     switch (keyHit)
  457.                     {
  458.                         case 0x1F:    //down arrow
  459.                             theItem = helpNextButton;
  460.                             HandleHelpItems(sHelp,&theItem);
  461.                             break;
  462.                         case 0x1E:    // up arrow
  463.                             theItem = helpPrevButton;
  464.                             HandleHelpItems(sHelp,&theItem);
  465.                             break;
  466.                     }
  467.                     return(TRUE);
  468.                     break;    
  469.             }
  470.         }
  471.     }
  472.     else
  473.         return(FALSE);
  474. }
  475.  
  476.  
  477. /*--------------------------------------------------------------------------------------*/
  478.  
  479. pascal void TopicListDef(short lMsg,Boolean lSelect,Rect *lRect,Cell lCell,
  480.                             short lDataOffset,short lDataLength,ListHandle theList)
  481. {
  482.     /* this is the list definition function for th topic list. It is embedded in this code
  483.         and will be called by the list manager using a 'sneaky jump'. */
  484.     
  485.     switch (lMsg)
  486.     {
  487.         case lInitMsg:
  488.             break;
  489.         case lDrawMsg:
  490.             DrawHelpTopicCell(lCell,lDataLength,theList,lRect);
  491.             if (!lSelect)
  492.                 break;
  493.         case lHiliteMsg:
  494.             SetHiliteMode();
  495.             InvertRect(lRect);
  496.             break;
  497.         case lCloseMsg:
  498.             break;
  499.     }
  500. }
  501.  
  502.  
  503. void    DrawHelpTopicCell(Cell tCell,short dataLen,ListHandle theList,Rect *dCell)
  504. {
  505.     short                tLen;
  506.     bigTopicRecPtr        tData;
  507.     bigTopicRec            tRec;
  508.     FontInfo            fInfo;
  509.     SimHelpHdl            sHelp;
  510.     short                indentPix,saveFont,saveSize;
  511.     
  512.     sHelp = (SimHelpHdl)(*theList)->userHandle;        // might be handy...
  513.     
  514.     tLen = dataLen;
  515.     tData = &tRec;
  516.     LGetCell((Ptr) tData,&tLen,tCell,theList);
  517.     
  518.     saveFont = qd.thePort->txFont;
  519.     saveSize = qd.thePort->txSize;
  520.  
  521.     TextFont(geneva);
  522.     TextSize(9);
  523.     GetFontInfo(&fInfo);
  524.     
  525.     indentPix = tRec.indent * (*sHelp)->indentPixels;
  526.     MoveTo(dCell->left + indentPix + 1,dCell->top + fInfo.ascent - 1);
  527.     
  528.     TextFace(tRec.tStyle);
  529.     DrawText(&tData->topicString,1,tData->topicString[0]);
  530.     
  531.     TextFace(0);
  532.     TextFont(saveFont);
  533.     TextSize(saveSize);
  534. }
  535.  
  536.  
  537. short    GetHypertextStyleRef(TEHandle teRec,short theStyle)
  538. {
  539.     /* returns an index value which represents the index in the StyleRun table of the
  540.         entry which matches the given style. You need this to look up a hypertext link.
  541.         Call after installing a new page. */
  542.         
  543.     TEStyleHandle    teStyles;
  544.     short            i;
  545.     STHandle        styleTab;
  546.     STElement        styleEntry;
  547.     
  548.     if (teRec != NIL)
  549.     {
  550.         teStyles = GetStylHandle(teRec);
  551.         
  552.         if (teStyles != NIL)
  553.         {
  554.             styleTab = (*teStyles)->styleTab;
  555.             
  556.             for (i = 0; i < (*teStyles)->nStyles; i++)
  557.             {
  558.                 styleEntry = (*styleTab)[i];
  559.                 
  560.                 if (styleEntry.stFace == theStyle)
  561.                     return(i);
  562.             }
  563.         }
  564.     }
  565.     return(-1);
  566. }
  567.  
  568.  
  569. short    ResolveHypertextLink(SimHelpHdl    sHelp,Point clickPt)
  570. {
  571.     /* call after clicking in the text pane. This function resolves whether a hypertext
  572.         link was clicked, handling all of the necessary feedback, such as highlighting,
  573.         etc. It returns the page ID of the link, or -1 if not a link or page missing */
  574.         
  575.     TEHandle        teRec;
  576.     short            charOffset,index,hypTextLen,pageRef = -1,i;
  577.     GrafPtr            savePort;
  578.     TEStyleHandle    teStyles;
  579.     StyleRun        stRun,nextRun;
  580.     long            ignored;
  581.     Ptr                textStart;
  582.     Str255            hyperString;
  583.     htIndexHdl        hypIndex;
  584.     Rect            wordRect;
  585.     Boolean            trackPointIn,wasIn;
  586.     
  587.     if (sHelp != NIL && (*sHelp)->hyperTextIndex != -1)
  588.     {
  589.         teRec = GetTDTextHdl((*sHelp)->ownerWindow);
  590.         if (teRec != NIL)
  591.         {
  592.             teStyles = GetStylHandle(teRec);
  593.             
  594.             if (teStyles != NIL)
  595.             {
  596.                 GetPort(&savePort);
  597.                 SetPort((*sHelp)->ownerWindow);
  598.                 GlobalToLocal(&clickPt);
  599.                 
  600.                 charOffset = TEGetOffset(clickPt,teRec);
  601.                 
  602.                 if (charOffset > 0 && charOffset < (*teRec)->teLength)
  603.                 {
  604.                     // scan the runs array for the style of the clicked char
  605.         
  606.                     for (index = 0;index < (*teStyles)->nRuns;index++)
  607.                     {
  608.                         stRun = (*teStyles)->runs[index];
  609.                         nextRun = (*teStyles)->runs[index +1];
  610.                         
  611.                         if (charOffset >= stRun.startChar && charOffset < nextRun.startChar)
  612.                         {
  613.                             /* we found the char. Does the hypertext index match? */
  614.                             
  615.                             if (stRun.styleIndex == (*sHelp)->hyperTextIndex)
  616.                             {
  617.                                 /* yes- fetch the string and hilite it */
  618.                                 
  619.                                 TESetSelect(stRun.startChar,nextRun.startChar,teRec);
  620.                                 TEActivate(teRec);
  621.                                 
  622.                                 wordRect = (*teRec)->selRect;
  623.                                 /* track the rect as long as the mouse is down */
  624.                                 
  625.                                 trackPointIn = wasIn = TRUE;
  626.                                 
  627.                                 while (WaitMouseUp())
  628.                                 {
  629.                                     GetMouse(&clickPt);
  630.                                     trackPointIn = PtInRect(clickPt,&wordRect);
  631.                                     if (trackPointIn &! wasIn)
  632.                                         TEActivate(teRec);
  633.                                     else
  634.                                         if (wasIn &! trackPointIn)
  635.                                             TEDeactivate(teRec);
  636.                                     wasIn = trackPointIn;
  637.                                 }
  638.                                 if (wasIn)
  639.                                 {
  640.                                     for(i = 0;i < 3;i++)
  641.                                     {
  642.                                         TEDeactivate(teRec);
  643.                                         Delay(5,&ignored);
  644.                                         TEActivate(teRec);
  645.                                         Delay(5,&ignored);
  646.                                     }
  647.                                     TEDeactivate(teRec);
  648.                                     hypTextLen = nextRun.startChar - stRun.startChar;
  649.                                     textStart = (Ptr)(*(*teRec)->hText + stRun.startChar);
  650.                                     BlockMove(textStart,&hyperString[1],hypTextLen);
  651.                                     hyperString[0] = hypTextLen;
  652.                                     
  653.                                     /* now search the hypertext index for this page to match
  654.                                         this string */
  655.                                         
  656.                                     hypIndex = (htIndexHdl) GetResource(hyperTextIndexType,
  657.                                                                     (*sHelp)->curPageResID);
  658.                                     if (hypIndex != NIL)
  659.                                     {
  660.                                         pageRef = MatchHyperLink(&hyperString,hypIndex);
  661.                                         HPurge((Handle) hypIndex);
  662.                                         ReleaseResource((Handle) hypIndex);
  663.                                     }
  664.                                 }
  665.                                 break;    // jump out of the loop
  666.                             }
  667.                         }
  668.                     }
  669.                 }
  670.                 SetPort(savePort);
  671.             }
  672.         }
  673.     }
  674.     return(pageRef);
  675. }
  676.  
  677.  
  678. short    MatchHyperLink(Str255 *testStr,htIndexHdl pageIndex)
  679. {
  680.     /* searches the page index record for a match with the test string. When found, the
  681.         corresponding page ID is returned, otherwise, -1 is returned */
  682.         
  683.     Ptr            recStart;
  684.     long        recSize;
  685.     short        recCount,index;
  686.     hypEntry    curEntry;
  687.     
  688.     if (pageIndex != NIL)
  689.     {
  690.         HNoPurge((Handle) pageIndex);
  691.         
  692.         recCount = (*pageIndex)->nEntries;
  693.         MoveHHi((Handle) pageIndex);
  694.         HLock((Handle) pageIndex);
  695.         
  696.         recStart = (Ptr) &(*pageIndex)->hEntries[0];
  697.         
  698.         for (index = 0;index < recCount;index++)
  699.         {
  700.             recSize = sizeof(hypEntry); 
  701.             BlockMove(recStart,&curEntry,recSize);
  702.             
  703.             if (EqualString(*testStr,curEntry.htMatchString,FALSE,FALSE))
  704.             {
  705.                 HUnlock((Handle) pageIndex);
  706.                 return(curEntry.pageID);
  707.             }    
  708.             recSize = curEntry.htMatchString[0] + sizeof(short) + 1;
  709.             recStart += recSize;
  710.         }
  711.         HUnlock((Handle) pageIndex);
  712.     }
  713.     return(-1);
  714. }
  715.  
  716.  
  717. void        SetHelpResFile(SimHelpHdl sHelp,short refNum)
  718. {
  719.     /* sets the help file resource refnum */
  720.     
  721.     (*sHelp)->helpResFileRef = refNum;
  722. }
  723.  
  724.  
  725. void        SwapHelpResFile(SimHelpHdl sHelp,Boolean hSwapContext)
  726. {
  727.     /* switches the resource files according to the flag */
  728.     
  729.     if (hSwapContext == kSwapHelpIn)
  730.     {
  731.         (*sHelp)->swapResFileRef = CurResFile();
  732.         if ((*sHelp)->helpResFileRef != -1)
  733.             UseResFile((*sHelp)->helpResFileRef);
  734.     }
  735.     else
  736.     {
  737.         if ((*sHelp)->swapResFileRef != -1)
  738.             UseResFile((*sHelp)->swapResFileRef);
  739.     }
  740. }
  741.